home *** CD-ROM | disk | FTP | other *** search
- /************************************************************************
- * "Epsilon", "EEL" and "Lugaru" are trademarks of Lugaru Software, Ltd. *
- * *
- * Copyright (C) 1985 Lugaru Software Ltd. All rights reserved. *
- * *
- * Limited permission is hereby granted to reproduce and modify this *
- * copyrighted material provided that the resulting code is used only in *
- * conjunction with Lugaru products and that this notice is retained in *
- * any such reproduction or modification. *
- ************************************************************************/
-
- /*
- * Modifications copyright (c) 1985 by David Dyer-Bennet
- * Permission for non-commercial use is hereby granted; all other
- * rights are reserved.
- *
- * Modifications by David Dyer-Bennet
- * Terrabit Software
- * 4242 Minnehaha Ave S
- * Minneapolis, MN 55406
- * Sysop of Fido 14/341, The Terraboard, (612) 721-8967 3/12/24 24hrs
- * (612) 721-8800 NOT 24 hrs! More like noon to midnight
- */
-
- /*
- * Revision history:
- *
- * Edit Date Who Description
- *
- * Version 1.0
- * 0 12-Nov-85 Lugaru Epsilon Version 3.01
- * 1 3-Jan-86 DD-B Add support for comment.e
- * 2 4-Jan-86 DD-B Add error definition for next-error
- * for Microsoft C compiler
- * 3 6-Jan-86 DD-B Add E mode for eel error definition
- */
-
- #include "eel.h"
- #include "comment.h" /* [1] Global vars */
-
- /* [2] Define format of compiler error messages for proc.e */
- buffer char *error_recog;
- buffer char *erfile_recog;
- buffer char *erline_recog;
-
- /*
- Automatic indentation for C and EEL code. Several indenting styles
- are supported, selected by the following variables.
- The position of the closing brace is controlled by the Closeback variable:
-
- Closeback = 0; Closeback = 1;
- if (foo) { if (foo) {
- bar(); bar();
- baz(); baz();
- } }
-
- If Closeback = 0 the following style may also be used:
- if (foo)
- {
- bar();
- baz();
- }
-
- */
- int Closeback = 1;
- /*
- The Topindent variable controls whether top-level statements in a function
- are indented:
-
- Topindent = 0; Topindent = 1;
- foo() foo()
- { {
- if (bar) if (bar)
- baz(); baz();
- } }
- */
- int Topindent = 1;
-
- /*
- The Matchdelim variable controls whether typing ), ], or } displays the
- corresponding (, [, or { when the former is typed. It uses the
- show-matching-delimiter command.
- */
- int Matchdelim = 1;
-
-
- keytable c_tab; /* key table for c mode */
-
- /* by default, the indenting levels are one tab stop apart */
- #define INCR 4 /* [1] */
-
- /* define an RE matching C comments or whitespace */
- #define C_SKIP "((/%*([^*]|%*[^/])*%*/)|[ \t\n])*"
-
- c_indenter() /* replace surrounding indentation with new */
- {
- to_column(c_compute_indent());
- }
-
- command c_mode()
- {
- mode_keys = c_tab; /* use these keys */
- if (Matchdelim)
- c_tab[')'] = c_tab[']'] = (short) show_matching_delimiter;
- major_mode = strsave("C");
- make_mode();
- indenter = c_indenter;
- auto_indent = 1;
- /* [1] Define C comments for the comment package */
- comment_recog = "((/%* )|(/%*))!(.*)%*/$";
- comment_begin = "/* ";
- comment_end = " */";
- comment_col = 32;
- comment_limit = 60;
- /* [1] end insert */
- /* [2] Show next-error what an error looks like */
- error_recog = "^[a-zA-Z0-9_.%/:]+%([0-9]+%) :.*";
- /* Microsoft C */
- /* errors look like: file(line): */
-
- erfile_recog = "([a-zA-Z0-9_.%/:]+)%(";
- erline_recog = "([0-9]+)%)";
- /* [2] End insert */
- }
-
- /* [3]
- * Special "e" mode, which differs from c only in the error finding
- */
- command e_mode ()
- {
- c_mode ();
- major_mode = strsave("E");
- make_mode ();
- error_recog = "^[a-zA-Z0-9_.%/:]+[ \t]+[0-9]+:"; /* Eel */
- erfile_recog = "([a-zA-Z9-0_.%/:]+)[ \t]+";
- erline_recog = "([0-9]+):";
- } /* end e_mode () */
-
- /* make this the default mode for .c, .h, and .e files */
- suffix_c() { c_mode(); }
- suffix_h() { c_mode(); }
- suffix_e() { e_mode(); }
-
- /* Look at the last two lines and return the correct indentation
- for the current line, assuming C source (or similar). At start,
- we must be at the end of a line's indentation.
- */
-
- c_compute_indent()
- {
- int orig = point, prev_keyword;
- int prev_end = ';', prev2_end = ';'; /* last chr on 2 prev lines */
- int ind = 0; /* indentation to use */
- int first_char; /* cur line's first char */
-
- first_char = curchar();
- to_begin_line();
- re_search(-1, C_SKIP); /* skip whitespace and comments */
- if (point > 0) {
- prev_end = character(--point); /* get last relevant char */
- to_indentation();
- ind = current_column(); /* and indentation of its line */
- prev_keyword = point; /* save its position too */
-
- re_search(-1, C_SKIP); /* skip whitespace and comments */
- if (point > 0) /* and get last interesting char on */
- prev2_end = character(point-1); /* line before that */
-
- point = prev_keyword; /* prepare for checking prev line */
- }
-
- if (!ind) { /* special case if no previous indentation */
- if (top_indent(prev_end, prev2_end))
- ind += INCR;
- } else if (prev_end == ';') {
- if (!index(";{}", prev2_end))
- ind -= INCR;
- } else if (prev_end == '}') {
- if (!Closeback)
- ind -= INCR;
- } else if (prev_end != '{' || index(";{}", prev2_end)
- || c_statement_start())
- ind += INCR;
- /* otherwise, last is probably continuation of a stmt or func decl */
- if (Closeback && first_char == '}')
- ind -= INCR;
- point = orig;
- return ind;
- }
-
- /* Look at the last two lines and guess at the correct indentation,
- assuming C source (or similar). If we're not in this line's
- indentation, though, or our new indentation matches the old,
- just insert a tab.
- */
-
- c_indent() on c_tab['\t']
- {
- int orig = point;
- int orig_column = current_column();
-
- to_indentation();
- if (orig_column > current_column()) { /* if not in indentation */
- point = orig;
- insert('\t'); /* insert a tab */
- } else if (prev_cmd == C_INDENT) /* repeated, make bigger */
- to_column(orig_column + INCR);
- else
- to_column(c_compute_indent());
- this_cmd = C_INDENT;
- }
-
- /*
- Tell if more indent is required.
- Assumes last line had no indent and point is at its start.
- The hard case is distinguishing between these when Topindent is zero:
-
- foo(); foo();
- } }
- func(bar) if (bar)
-
- When point is just after these examples, we must examine the word
- at "func" to distinguish the left example (the end of a function and
- beginning of the next, requiring no indentation) from the right (the
- end of a block and start of a conditional, requiring indentation).
- */
- top_indent(prev_end, prev2_end)
- {
- int ret;
-
- if (Topindent)
- ret = prev_end == '{';
- else if (ret = !index(";}", prev_end) && index(";{}", prev2_end))
- if (prev_end != '{' && !c_statement_start())
- ret = 0;
- return ret;
- }
-
- /*
- Tell if the last line begins a statement (rather than a function
- declaration or the continuation of a previous statement).
- Assumes point is at the start of the last line.
- */
- c_statement_start()
- {
- return parse_string(1, "[{} \t]*(if|else|while|do|for)[^a-zA-Z0-9]",
- (char *) 0);
- }
-
- /* fix indentation if necessary when } is typed */
- c_close() on c_tab['}']
- {
- int orig = point;
- int orig_column; /* point's column */
- int ind;
-
- if (Closeback) {
- orig_column = current_column();
- to_indentation();
- ind = current_column(); /* get line's indentation */
- point = orig;
- if (orig_column <= ind) /* if in indentation */
- to_column(ind - INCR);
- }
- if (Matchdelim)
- show_matching_delimiter();
- else
- normal_character();
- }
-